﻿using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Xml.Serialization;

namespace LaunchPad.Core
{
    public class TrackTimeline : ObservableCollection<TrackEvent>
    {
        private TimeSpan _finish;
        private TimeSpan _start;

        public TrackTimeline()
        {
            CollectionChanged += TrackTimelineCollectionChanged;
            UpdateTimelineStats();
        }

        [XmlIgnore]
        public TimeSpan Start
        {
            get { return _start; }
            private set
            {
                if (_start != value)
                {
                    _start = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("Start"));
                    OnPropertyChanged(new PropertyChangedEventArgs("Header"));
                }
            }
        }

        [XmlIgnore]
        public TimeSpan Finish
        {
            get { return _finish; }
            private set
            {
                if (_finish != value)
                {
                    _finish = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("Finish"));
                    OnPropertyChanged(new PropertyChangedEventArgs("Header"));
                }
            }
        }

        [XmlIgnore]
        public string Header
        {
            get
            {
                return string.Format("Timeline {0} -> {1} ({2} events)", Start.ToString("g"), Finish.ToString("g"),
                                     Count);
            }
        }

        private void TrackTimelineCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null)
            {
                foreach (TrackEvent ete in e.NewItems)
                    ete.PropertyChanged += TrackEventPropertyChanged;
            }

            if (e.OldItems != null)
            {
                foreach (TrackEvent ete in e.OldItems)
                    ete.PropertyChanged -= TrackEventPropertyChanged;
            }

            UpdateTimelineStats();
        }

        private void TrackEventPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            UpdateTimelineStats();
        }

        private void UpdateTimelineStats()
        {
            if (Count == 0)
            {
                Start = TimeSpan.Zero;
                Finish = TimeSpan.Zero;
            }
            else
            {
                Start = this.Min(tle => tle.Start);
                Finish = this.Max(tle => tle.Finish);
            }
        }

        public bool Intersects(TimeSpan time)
        {
            return this.Any(e => e.Intersects(time));
        }

        public bool Intersects(TimeSpan start, TimeSpan finish)
        {
            return this.Any(e => e.Intersects(start, finish));
        }

        public bool Intersects(TrackEvent e)
        {
            return this.Any(ev => ev.Intersects(e));
        }

        public bool TryAddEvent(TrackEvent e)
        {
            if (Intersects(e))
                return false;

            Add(e);
            return true;
        }

        protected override void ClearItems()
        {
            while (Count > 0)
                RemoveAt(0);
        }
    }
}